package com.gitee.apanlh.util.dataformat;

import com.gitee.apanlh.exp.XmlConvertException;
import com.gitee.apanlh.util.base.StringUtils;
import com.gitee.apanlh.util.check.CheckImport;
import com.gitee.apanlh.util.check.CheckLibrary;
import com.gitee.apanlh.util.dataformat.xml.XStreamFactory;
import com.gitee.apanlh.util.encode.StrEscapeUtils;
import com.gitee.apanlh.util.reflection.ClassUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;

import java.util.List;

/**
 * 	基于Xstream的工具类
 *
 *	@author Pan
 */
public class XStreamUtils {
	
	static {
		CheckImport.library(CheckLibrary.XSTREAM);
	}
	
	/**
	 * 	构造函数
	 * 
	 * 	@author Pan
	 */
	private XStreamUtils() {
		//	不允许外部实例
		super();
	}
	
	/**
	 * 	XML转换成Bean 需要实体类加上自定义注解
	 * 	<br>默认字符集为 UTF-8
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  xmlStr	 xml字符串
	 * 	@param  clazz	 类
	 * 	@return T
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toBean(String xmlStr, Class<T> clazz) {
		T bean = null;
		try {
			bean = (T) XStreamFactory.instance(clazz).fromXML(xmlStr);
		} catch (Exception e) {
			throw new XmlConvertException(StringUtils.format("xml转换Bean失败 class为:{},异常原因为:{}", clazz.getName(), e.getMessage(), e));
		} 
		return bean;
	}
	
	/**	
	 * 	XML转换成Bean 
	 * 	<br>需要实体类加上自定义注解
	 * 
	 * 	@author Pan
	 * 	@param  <T>      数据类型
	 * 	@param  xmlStr   xml字符串
	 * 	@param  clazz    实体类
	 * 	@param  charset  字符集
	 * 	@return 实体类
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toBean(String xmlStr, Class<T> clazz, String charset) {
		Object bean = null;
		try {
			bean = XStreamFactory.instance(charset, new Class[] {clazz}).fromXML(xmlStr);
		} catch (Exception e) {
			throw new XmlConvertException(StringUtils.format("Xml转换Bean失败,class为:{},异常原因为:{}", clazz.getName(), e.getMessage(), e));
		}
		
		return (T) bean;
	}
	
	/**	
	 * 	将Bean转换解析成xml
	 * 	开启扫描注解
	 * 
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param  bean	javaBean
	 * 	@return	String	xml
	 */
	public static <T> String toXml(T bean) {
		Assert.isNotNull(bean);
		
		return XStreamFactory.instance(bean).toXML(bean);
	}
	
	/**	
	 * 	将Bean转换解析成xml
	 * 	<br>Bean需要添加注解
	 * 
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param  bean	javaBean
	 * 	@param  clazz	类
	 * 	@return	String	xml
	 */
	public static <T> String toXml(T bean, Class<T> clazz) {
		Assert.isNotNull(bean);
		
		if (clazz != bean.getClass()) {
			throw new XmlConvertException(StringUtils.format("转换Xml失败 原因是bean类型不一致 传入的Bean为:{}, 泛型Bean为:{}", bean.getClass(), clazz));
		}
		
		return XStreamFactory.instance(clazz).toXML(bean);
	}
	
	/**	
	 * 	将ListBean转换至XML
	 * 
	 * 	@author Pan
	 * 	@param  <T>     数据类型
	 * 	@param 	list	集合
	 * 	@return	String
	 */
	public static <T> String toXml(List<T> list) {
		if (ValidParam.isEmpty(list)) {
			return null;
		}
		return XStreamFactory.instance(ClassUtils.getClass(list)).toXML(list);
	}
	
	/**	
	 * 	将XML值保留{@code <data>xxx</data>}部分 并且替换转义符
	 * 
	 * 	@author Pan
	 * 	@param  xml	  xml
	 * 	@return	String
	 */
	public static String filterXml(String xml) {
		return filterXml(xml, "data");
	}
	
	/**	
	 * 	将XML值保留输入的过滤标签
	 * 
	 * 	@author Pan
	 * 	@param  xml			xml
	 * 	@param  bodyAlias	过滤标签
	 * 	@return	String
	 */
	public static String filterXml(String xml, String bodyAlias) {
		Assert.isNotEmpty(xml);
		
		String s = StringUtils.format("<{}>", bodyAlias);
		String e = StringUtils.format("</{}>", bodyAlias);
		return StrEscapeUtils.unescapeXml(xml.substring(xml.indexOf(s), xml.indexOf(e) + e.length()));
	}
}
